using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using System.IO;
using System.Text;
using System.Reflection;
using System.Text.RegularExpressions;


public class GenUICode : EditorWindow
{
    public string filter_namespaces_s = "//开始引入命名空间不覆盖";
    public string filter_namespaces_e = "//结束引入命名空间不覆盖";
    public string filter_comp_s = "    //自动生成组件每次生成都会覆盖";
    public string filter_comp_e = "    //自动生成组件结束";
    public string filter_awake_s = "        //Awake 不覆盖区域开始";
    public string filter_awake_e = "        //Awake 不覆盖区域结束";
    public string filter_gen_s = "    //自动生成组件函数实现开始";
    public string filter_gen_e = "    //自动生成组件函数实现结束";
    public string filter_over_s = "    //开始写入不覆盖";
    public string filter_over_e = "    //结束写入不覆盖";

    public string outPath = "";
    public string defaultPath = "/Scripts/UI/AutoGenerate";
    List<string> filters = new List<string>();
    bool is_item = false;

    public GameObject template{
        get{
            return prefab;
        }
        set{
            prefab = value;
        }
    }

    //需要操作的组件名字
    public List<CompInfo> pathList = new List<CompInfo>();
    GameObject prefab;
    // [MenuItem("UI/GenUICode")]
    public static void ShowWindow()
    {
        GenUICode window = (GenUICode)EditorWindow.GetWindow(typeof(GenUICode));
        window.position = new Rect(0, 0, 800, 600);
    }

    //OnGui
    private void OnGUI()
    {
        GUILayout.Label("UINewFile", EditorStyles.boldLabel);


        //横向布局
        EditorGUILayout.BeginHorizontal();
        if(outPath == "")
        {
            outPath = Application.dataPath + defaultPath;
        }

        outPath = EditorGUILayout.TextField("输出路径", outPath);
        //button
        if(GUILayout.Button("Set OutPath"))
        {   
            //设置输出路径
            outPath = EditorUtility.OpenFolderPanel("Select OutPath", outPath, "");
            Debug.Log(outPath);
            if(outPath == "")
            {
                outPath = Application.dataPath + defaultPath;
            }

        }

        EditorGUILayout.EndHorizontal();

        //gameobject field
        prefab = (GameObject)EditorGUILayout.ObjectField("Prefab", prefab, typeof(GameObject), false);

        EditorGUILayout.LabelField("是否是Item 如果是Item则会生成一个Item类 在输出目录下生成文件 不会像UI类一样生成一个文件夹");
        is_item = EditorGUILayout.Toggle("Is Item", is_item);


        //button
        if(GUILayout.Button("Create UI File"))
        {   
            if(prefab == null)
            {
                Debug.LogError("prefab is null");
                return;
            }
            CreateUIFile();
        }


        //button
        if(GUILayout.Button("Add Component"))
        {   
            if(prefab == null)
            {
                Debug.LogError("prefab is null");
                return;
            }
            AddComponent();
        }

    }

    //获取Prefab的组件信息
    void GetPrefabCompInfo()
    {
        //清空pathlist
        pathList.Clear();
        filters.Clear();

        //获取gameobject所有子节点
        Transform[] children = prefab.GetComponentsInChildren<Transform>(true);
        foreach(Transform child in children)
        {
            bool is_prefab = PrefabUtility.IsAnyPrefabInstanceRoot(child.gameObject);
            if(is_prefab)
            {
                string path = GetGameObjectPath(child.gameObject);
                path = path.Substring(path.IndexOf('/') + 1);
                filters.Add(path + "/");
            }
            //分割字符串
            string[] paths = child.name.Split('_');
            if(paths.Length > 2)
            {
                bool is_op = paths[0] == "OP";
                //添加到pathlist
                if(is_op)
                {
                    // CompInfo info = new CompInfo();

                    string path = GetGameObjectPath(child.gameObject);
                    path = path.Substring(path.IndexOf('/') + 1);
                    // info.path = path.Substring(path.IndexOf('/') + 1);
                    bool is_filter = false;
                    if(filters.Count > 0)
                    {
                        foreach(string filter in filters)
                        {
                            if(path.Contains(filter))
                            {
                                is_filter = true;
                                break;
                            }
                        }
                    }
                    if(is_filter == false)
                    {
                        CompInfo info = new CompInfo();
                        info.path = path;
                        info.type = paths[1];
                        info.name = paths[2] + "_" + paths[1].ToLower();
                        pathList.Add(info);
                    }
                }
            }
        }
    }

    //递推获取gameobject tree path
    string GetGameObjectPath(GameObject go)
    {
        string path = go.name;
        Transform parent = go.transform.parent;
        while(parent != null)
        {
            path = parent.name + "/" + path;
            parent = parent.parent;
        }
        return path;
    }

    //生成UI文件
    void CreateUIFile()
    {
        GetPrefabCompInfo();
        //IO 创建文件
        string path = outPath + $"/{prefab.name}";
        string file_path = path + $"/{prefab.name}.cs";
        if(is_item)
        {
            path = outPath + "/";
            file_path = path + $"/{prefab.name}Item.cs";
        }
        //if directory not exist, create it
        if(!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }

        //if file exist, save data in string reader
        if(File.Exists(file_path))
        {
            //读取文件
            StreamReader sr = new StreamReader(file_path);
            string file_content = sr.ReadToEnd();
            sr.Close();
            //删除文件
            File.Delete(file_path);
            //创建文件
            FileStream fs = new FileStream(file_path, FileMode.Create);
            StringBuilder sb = new StringBuilder();
            // string headOldCode = RegexString(file_content,filter_namespaces_s, filter_namespaces_e);
            string headOldCode = RegexMgr.Instance.RegexBeginAndEnd(file_content,filter_namespaces_s, filter_namespaces_e);
            WriteHead(sb,headOldCode);
            string compOldCode = RegexMgr.Instance.RegexBeginAndEnd(file_content, filter_comp_s, filter_comp_e);
            WriteComp(sb, pathList.ToArray(),compOldCode);
            string awakeOldCode = RegexMgr.Instance.RegexBeginAndEnd(file_content, filter_awake_s,filter_awake_e);
            WriteAwake(sb,pathList.ToArray(),awakeOldCode);
            string oldGenCode = RegexMgr.Instance.RegexBeginAndEnd(file_content, filter_gen_s, filter_gen_e);
            GenerateCode(sb, pathList.ToArray(),oldGenCode);
            string oldOverCode = RegexMgr.Instance.RegexBeginAndEnd(file_content, filter_over_s, filter_over_e);
            WriteNotCover(sb,oldOverCode);

            WriteEnd(sb);
            fs.Write(Encoding.UTF8.GetBytes(sb.ToString()), 0, Encoding.UTF8.GetBytes(sb.ToString()).Length);
            fs.Close();
        }else{
            //创建文件
            FileStream fs = new FileStream(file_path, FileMode.Create);
            StreamWriter sw = new StreamWriter(fs);
            //写入文件
            StringBuilder sb = new StringBuilder();
            WriteHead(sb);

            WriteComp(sb, pathList.ToArray());

            WriteAwake(sb,pathList.ToArray());
            GenerateCode(sb, pathList.ToArray());
            //写入不覆盖的代码
            WriteNotCover(sb);
            //写入尾部
            WriteEnd(sb);

            sw.Write(sb.ToString());
            sw.Close();
            fs.Close();
        }


        // AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }

    void WriteHead(StringBuilder sb,string oldCode = "")
    {
        string class_base = is_item ? "UIItem" : "UIBase";
        string class_name = is_item ? prefab.name + "Item" : prefab.name;
        sb.AppendLine(filter_namespaces_s);
        if(oldCode == "")
        {
            sb.AppendLine("using System.Collections;");
            sb.AppendLine("using System.Collections.Generic;");
            sb.AppendLine("using UnityEngine;");
            sb.AppendLine("using UnityEngine.UI;");

        }else{
            sb.AppendLine(oldCode.Trim());
        }
        sb.AppendLine(filter_namespaces_e);
        sb.AppendLine("");
        sb.AppendLine("public class " + class_name + " : " + class_base);
        sb.AppendLine("{");

    }

    //写入组件
    void WriteComp(StringBuilder sb, CompInfo[] info,string oldCode = "")
    {
        sb.AppendLine(filter_comp_s);
        for (int i = 0; i < info.Length; i++)
        {
            string genCode = "    public " + info[i].type + " " + info[i].name + ";";
            //if old code not contain new code, do write
            if(!oldCode.Contains(genCode))
            {
                sb.AppendLine(genCode);
            }else{
                // Debug.Log("old code contain new code");
            }

        }
        if(oldCode != "")
            sb.AppendLine("    " + oldCode.Trim());

        sb.AppendLine(filter_comp_e);
    }

    //写入Start
    void WriteStart(StringBuilder sb, CompInfo[] info,string oldCode = "")
    {
        sb.AppendLine("    public void Start()");
        sb.AppendLine("    {");
        sb.AppendLine("    }");
    }

    void WriteAwake(StringBuilder sb, CompInfo[] info,string oldCode = "")
    {
        sb.AppendLine("");
        sb.AppendLine("    public void Awake()");
        sb.AppendLine("    {");
        sb.AppendLine("        //自动生成组件绑定函数，每次生成都会覆盖");
        sb.AppendLine("        AutoBind();");
        sb.AppendLine("        //自动生成组件绑定函数结束");
        sb.AppendLine("");
        sb.AppendLine(filter_awake_s);
        sb.AppendLine("        " + oldCode.Trim());
        sb.AppendLine(filter_awake_e);
        sb.AppendLine("    }");
        sb.AppendLine("");
        sb.AppendLine("    public void AutoBind()");
        sb.AppendLine("    {");
        foreach (var item in info)
        {
            switch (item.type)
            {
                case "Button":
                    string str = $"        {item.name}.onClick.AddListener(OnClick{item.name});";
                    sb.AppendLine(str);
                    break;
                default:
                    break;
            }
        }
        sb.AppendLine("    }");
    }

    //写入尾部
    void WriteEnd(StringBuilder sb)
    {
        sb.AppendLine("");
        sb.AppendLine("");
        sb.AppendLine("}");
    }

    //写入不覆盖区域
    void WriteNotCover(StringBuilder sb,string oldCode = "")
    {
        sb.AppendLine(filter_over_s);
        if(oldCode != "")
        {
            sb.AppendLine("    " + oldCode.Trim());
        }else{
            sb.AppendLine("    //逻辑代码写在这里");
            if(is_item == false)
            {
                sb.AppendLine("    public override void Refresh()");
                sb.AppendLine("    {");
                sb.AppendLine("        base.Refresh();");
                sb.AppendLine("    }");
            }

        }
        // if(oldCode != "")
        //     sb.AppendLine("    " + oldCode.Trim());
        sb.AppendLine(filter_over_e);
    }

    void AddComponent()
    {
        GetPrefabCompInfo();
        GameObject item = AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GetAssetPath(prefab));
        //Assembly get type
        // var assembly = Assembly.GetAssembly(typeof(UIBase));
        // var type = assembly.GetType(prefab.name);
        Type class_type = is_item ? typeof(UIItemCfg) : typeof(UIBase);
        string class_name = is_item ? prefab.name + "Item" : prefab.name;
        var assembly = Assembly.GetAssembly(class_type);
        var type = assembly.GetType(class_name);
        Debug.Log(class_name);
        Debug.Log(type == null);
        var comp = item.GetComponent(type);
        if(comp != null){
            DestroyImmediate(comp,true);
            PrefabUtility.SavePrefabAsset(item);
        }

        item.AddComponent(type);
        comp = item.GetComponent(type);

        var compType = comp.GetType();
        foreach (var info in pathList)
        {
            var field = compType.GetField(info.name);
            //获取item的子物体
            var child = item.transform.Find(info.path);
            if(child == null)
            {
                Debug.LogError("child is null");
                return;
            }
            //获取子物体的组件
            var childComp = child.GetComponent(info.type);
            if(childComp == null)
            {
                Debug.LogError("childComp is null");
                return;
            }
            //设置组件
            field.SetValue(comp, childComp);
            Debug.Log("设置组件成功");
        }
        PrefabUtility.SavePrefabAsset(item);
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }

    //生成按钮代码
    string GenerateBtn(string name)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine($"    //{name}的点击函数");
        sb.AppendLine("    public void OnClick" + name + "()");
        sb.AppendLine("    {");
        sb.AppendLine("        //TODO");
        sb.AppendLine("    }");
        sb.AppendLine("");
        return sb.ToString();
    }

    void GenerateCode(StringBuilder sb, CompInfo[] info,string oldCode = "")
    {
        sb.AppendLine(filter_gen_s);
        foreach (var item in info)
        {
            switch (item.type)
            {
                case "Button":
                    string btn_code = GenerateBtn(item.name);
                    if(!oldCode.Contains("    public void OnClick" + item.name + "()"))
                    {
                        sb.AppendLine(btn_code);
                    }else{
                        Debug.Log("old code contain new code");
                    }
                    // sb.AppendLine(btn_code);
                    break;
                default:
                    break;
            }
        }
        if(oldCode != "")
            sb.AppendLine("    " + oldCode.Trim());

        sb.AppendLine(filter_gen_e);
        sb.AppendLine("");
    }

}